package com.techstar.ats.utils;

import java.io.*;
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import lombok.extern.slf4j.Slf4j;

import org.apache.commons.net.ftp.FTPClient;
import org.springframework.util.DigestUtils;
import com.techstar.ats.FtpProperties;
import com.techstar.ats.ScheduleMode;

@Slf4j
public class FtpHelper {
	public static final Charset GBK = Charset.forName("GBK");
	private static final String TMP_PATH = "/tmp/";
	private static final String FTP_PATH = "/%s/offline/";
	private static final String MD5_SUFFIX = ".md5";

	public static void ftpUp(FtpProperties ftpProperties, LocalDate date, String filePath) throws IOException {
		File file = new File(filePath);
		File fileMd5 = new File(filePath + ".md5");

		try(InputStream is = Files.newInputStream(file.toPath()); OutputStream os = new FileOutputStream(fileMd5, false);
		    OutputStreamWriter writer = new OutputStreamWriter(os, GBK)) {
			writer.write(String.format("%s %s", DigestUtils.md5DigestAsHex(is), file.getName()));

			String[] hosts = ftpProperties.getHosts();

			for(String host : hosts) {
				try {
					ftpProc(host, ftpProperties.getPort(), ftpProperties.getUsername(), ftpProperties.getPassword(),
						date, file, fileMd5);
				} catch(Exception ex) {
					log.error(ex.getMessage());
				}
			}
		}
	}

	private static void ftpProc(String host, int port, String username, String password,
		LocalDate date, File file, File fileMd5) throws IOException {
		FTPClient client = new FTPClient();

		try {
			client.connect(host, port);
			client.login(username, password);

			String ftpPath = getRemotePath(date);
			changeWorkingDirectory(client, ftpPath);

			try(InputStream is = Files.newInputStream(file.toPath())) {
				client.storeFile(ftpPath + file.getName(), is);
			}

			try(InputStream is = Files.newInputStream(fileMd5.toPath())) {
				client.storeFile(ftpPath + file.getName() + MD5_SUFFIX, is);
			}
		} finally {
			client.logout();
			client.disconnect();
		}
	}

	private static void changeWorkingDirectory(FTPClient client, String ftpPath) throws IOException {
		try {
			client.changeWorkingDirectory(ftpPath);
		} catch(IOException ex) {
			client.makeDirectory(ftpPath);
		}
	}

	public static String getLocalFile(LocalDate date, int line, ScheduleMode mode) {
		return TMP_PATH + getFileName(date, line, mode);
	}

	public static String getRemotePath(LocalDate date) {
		return String.format(FTP_PATH, date.format(DateTimeFormatter.BASIC_ISO_DATE));
	}

	public static String getFileName(LocalDate date, int line, ScheduleMode mode) {
		return String.format("%s_%03d_ats_%s.csv", date.format(DateTimeFormatter.BASIC_ISO_DATE), line, mode.literal());
	}
}
